#include "ColaImp.h"
#ifndef COLAIMP_CPP
#define COLAIMP_CPP

template <class T>
ColaImp<T>::ColaImp(int tam)
{
	this->maximo=tam;
	this->tope=0;
	heap = new NodoHeap<T>*[tam];
	for(int i=0;i<tam;i++) heap[i] = NULL;
}
template <class T>
ColaImp<T>::ColaImp(Puntero<ColaImp<T>> cola)
{
	this->maximo=cola->maximo;
	this->tope=cola->tope;
	heap = new NodoHeap<T>*[this->maximo];
	for(int i=0;i<this->maximo;i++) heap[i] = cola->heap[i];
}
template <class T>
ColaImp<T>::~ColaImp(void)
{
	for(int i =1; i<tope+1; i++){
		delete heap[i];
	}
	//this->lista=NULL;
	tope =0;
}
template <class T>
void ColaImp<T>::vaciar(){
	tope=0;
	for( int i=0;i<this->maximo;i++)
	{
		delete heap[i];
	}
}	
template <class T>
bool ColaImp<T>::esVacia(){
	return tope == 0;
}
template <class T>
bool ColaImp<T>:: encolarConPrioridad(T elemento, int puntaje){
		if(tope+1 < maximo){
			tope++;
			//If hash estaDefinido
			if(heap[1] == NULL) {
				//Si el array esta vacio inserto
				heap[1]=new NodoHeap<T>(elemento,puntaje);
				heap[1]->posicion=1;//lo pongo en la pos 1
				return true;
			}
			else{	
				int i;
				i = this->tope;
				//asigno el tope a i para saber hasta donde tengo que recorrer
				
				/*------------------------------------------------------------------------------------------------------------------------/
				#Tengo que hacer un metodo que si esta el recurso me devuelva la posicion donde esta y llame al cambiar puntaje recurso para
				#cumplir con el punto 3 del obligatorio hablar del tema de ordenes con el Santi porque es orden 1 promedio
				------------------------------------------------------------------------------------------------------------------------/*/
				while(i>1 && heap[i/2]->prioridad > puntaje){
					//comparo por puntaje para saber donde tengo que meter el recurso
					heap[i]=heap[i/2];
					heap[i]->posicion=i;
					i = i/2;
				}
				//inserto el recurso en la posicion correspondiente del heap	
				heap[i]=new NodoHeap<T>(elemento,puntaje);
				heap[i]->posicion=i;
				
				return true;
			}

	}else{
//Mirar bien Preguntar lo de la suma de puntaje o el cambio de puntaje
			//heap[pos]->dato=elemento;
			//heap[pos]->prioridad=puntaje;
			return true;
			
	
}
}
template <class T>
bool ColaImp<T>:: desencolar(T &dato)
{
	if(tope>=1){
		//me fijo si tengo elementos en el heap
		NodoHeap<T>* aux = heap[tope];
		tope--;
		//decremento el tope
		dato = heap[1]->dato;
		delete heap[1];
		//Elimino del hash el primero
		heap[1]=aux;
		heap[1]->posicion=1;
		//El elemento que estaba en el tope actualizo la posicion en el hash
		//pongo en la primera posicion el elemento elemento que quedo en el tope
		int hijo=1;
		//Filtrado ascendente ordenando el heap por prioridad que en nuestro caso es el puntaje
		for(int i=1; 2*i <= tope ; i=hijo){
			hijo = 2*i;
			if(hijo+1<=tope && heap[hijo+1]->prioridad > heap[hijo]->prioridad) hijo++;
			//Si fija en la posicion i y i+1 cual es mayor y lo corre a la posicion de i que es el padre
				if(heap[hijo]->prioridad > heap[i]->prioridad){
					aux = heap[i];
					heap[i] = heap[hijo];
					heap[hijo]=aux;
					//Corre el padre a la posicion del hijo
					heap[i]->posicion = i;
					heap[hijo]->posicion=hijo;
					//Actualizo la posicion heap
				}			
			
		}
		return true;
	}
	else {
		return false;
	}
}
template<class T>
Puntero<Iterador<T>> ColaImp<T>::ObtenerIterador() const
{
	Puntero<ListaImp<T>> lista=new ListaImp<T>();
	for(int i = 1; i < this->tope+1; i++){
			lista->AgregarPpio(heap[i]->dato);
	}
	Puntero<Iterador<T>> it=new IteradorListaImp<T>(lista);
	//delete lista;
	return it;
}
#endif